/**
 * @file           : led.hpp
 * @author         : Dmitry Karasev <karasevsdmitry@yandex.ru>
 * @brief          : LED driver
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2023 Dmitry Karasev
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************
 */

#pragma once

#include <stdint.h>
#include <stddef.h>
#include <limits>

#include "gpio.hpp"

namespace driver
{

namespace led
{

enum class mode_t : uint8_t
{
    SOLID = 0,
    BLINK
};

class led_t
{
public:
    static constexpr size_t BLINK_FOREVER = std::numeric_limits<uint32_t>::max();

    led_t(const device_t *port_ptr, uint8_t pin, bool is_active_low = false);

    bool init();

    void turn_on();
    void turn_off();

    void blink(uint32_t on_ms, uint32_t off_ms, size_t blinks_num = led_t::BLINK_FOREVER,
                   uint32_t pend_ms = 0);
    void set_silent_blink();
    void reset_silent_blink();

    void update_ms();

private:
    bool is_blinks_cnt_expired();
    static bool check_for_counter_zeroing(uint32_t *cnt_ptr);
    void reset_blinking();

    struct config_t
    {
        uint32_t on_timeout_ms;
        uint32_t off_timeout_ms;
        uint32_t pend_timeout_ms;
        size_t   blinks_num;
    } config;

    struct status_t
    {
        uint32_t on_ms;
        uint32_t off_ms;
        uint32_t pend_ms;
        size_t   blinks_cnt;
    } status;

    driver::gpio::gpio_t gpio;
    mode_t mode;
    bool is_silent_blink;
};

} // led

} // driver
